package com.hnchances.studentscoresystem.service.impl;

import com.hnchances.studentscoresystem.dto.request.UserLoginDTO;
import com.hnchances.studentscoresystem.dto.request.UserRegisterDTO;
import com.hnchances.studentscoresystem.dto.request.UserUpdateDTO;
import com.hnchances.studentscoresystem.dto.response.UserInfoResponse;
import com.hnchances.studentscoresystem.entity.Student;
import com.hnchances.studentscoresystem.entity.User;
import com.hnchances.studentscoresystem.exception.BusinessException;
import com.hnchances.studentscoresystem.exception.ErrorCode;
import com.hnchances.studentscoresystem.mapper.UserMapper;
import com.hnchances.studentscoresystem.service.StudentService;
import com.hnchances.studentscoresystem.service.UserService;
import com.hnchances.studentscoresystem.util.JwtUtil;
import com.hnchances.studentscoresystem.util.Md5Util;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 用户管理 Service 实现类（核心业务）
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User, Long, UserMapper> implements UserService {

    @Autowired
    private StudentService studentService;

    @Autowired
    private JwtUtil jwtUtil;

    // ====================== 基础 CRUD 实现 ======================
    @Override
    public boolean insert(User user) {
        // 补全默认值：状态默认 0（正常）、审核默认 1（已审核）
        if (user.getStatus() == null) {
            user.setStatus(0);
        }
        if (user.getVerify() == null) {
            user.setVerify(1);
        }
        if (user.getCreatDateTime() == null) {
            user.setCreatDateTime(new Date());
        }
        user.setUpdateDateTime(new Date());
        return mapper.insert(user) > 0;
    }

    @Override
    public User selectById(Long id) {
        return mapper.selectById(id);
    }

    @Override
    public List<User> selectAll() {
        return mapper.selectAll();
    }

    @Override
    public boolean update(User user) {
        user.setUpdateDateTime(new Date());
        return mapper.update(user) > 0;
    }

    @Override
    public boolean deleteById(Long id) {
        // 软删除：修改 status 为 1
        User user = new User();
        user.setId(id);
        user.setStatus(1);
        user.setUpdateDateTime(new Date());
        return mapper.update(user) > 0;
    }

    @Override
    public User selectByUserName(String userName) {
        return mapper.selectByUserName(userName);
    }

    // ====================== 核心业务实现 ======================
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(UserRegisterDTO registerDTO) {
        // 1. 身份校验：仅允许 0（学生）、1（老师）
        Integer identity = registerDTO.getIdentity();
        if (identity == null || (identity != 0 && identity != 1)) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "用户身份无效（仅支持学生0/老师1）");
        }

        // 2. 用户名唯一性校验
        if (selectByUserName(registerDTO.getUserName()) != null) {
            throw new BusinessException(ErrorCode.BUSINESS_ERROR, "用户名已存在");
        }

        // 3. 学生注册：校验身份证（确保班级存在该学生）
        Long studentId = null;
        if (identity == 0) {
            String idcard = registerDTO.getIdCard();
            if (idcard == null || idcard.trim().isEmpty()) {
                throw new BusinessException(ErrorCode.PARAM_ERROR, "学生注册需填写身份证号");
            }
            Student student = studentService.selectByIdcard(idcard);
            if (student == null) {
                throw new BusinessException(ErrorCode.BUSINESS_ERROR, "班级中无此学生信息，注册失败");
            }
            // 校验班级一致性（注册班级需与学生所属班级匹配）
            if (!registerDTO.getClassID().equals(student.getClassID())) {
                throw new BusinessException(ErrorCode.BUSINESS_ERROR, "注册班级与学生所属班级不匹配");
            }
            studentId = student.getId();
        }

        // 4. 老师注册：校验课程ID（老师需关联课程）
        if (identity == 1 && registerDTO.getCourseID() == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "老师注册需关联课程");
        }

        // 5. 密码加密（MD5 加盐）
        String encryptedPwd = Md5Util.md5Encrypt(registerDTO.getPassWord());

        // 6. 构建 User 实体并保存
        User user = new User();
        BeanUtils.copyProperties(registerDTO, user);
        user.setPassWord(encryptedPwd);
        user.setStudentID(studentId);
        user.setCreatDateTime(new Date());
        user.setUpdateDateTime(new Date());
        user.setStatus(0); // 正常状态
        user.setVerify(1); // 默认审核通过

        return insert(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String login(UserLoginDTO loginDTO, String loginIp) {
        // 1. 查询用户（状态正常）
        User user = selectByUserName(loginDTO.getUserName());
        if (user == null || user.getStatus() == 1) {
            throw new BusinessException(ErrorCode.BUSINESS_ERROR, "用户名不存在或已删除");
        }

        // 2. 密码校验（MD5 解密比对）
        String encryptedPwd = Md5Util.md5Encrypt(loginDTO.getPassWord());
        if (!encryptedPwd.equals(user.getPassWord())) {
            throw new BusinessException(ErrorCode.BUSINESS_ERROR, "密码错误");
        }

        // 3. 审核状态校验（仅审核通过可登录）
        if (user.getVerify() == 0) {
            throw new BusinessException(ErrorCode.BUSINESS_ERROR, "账号未审核通过，无法登录");
        }

        // 4. 更新最后登录信息（时间、IP）
        user.setLastLoginDateTime(new Date());
        user.setLoginIP(loginIp);
        update(user);

        // 5. 生成 JWT Token（包含用户ID、用户名、身份）
        return jwtUtil.generateToken(user.getId(), user.getUserName(), user.getIdentity());
    }

    @Override
    public UserInfoResponse getUserInfoByToken(String token) {
        // 1. Token 有效性校验
        if (jwtUtil.isTokenExpired(token)) {
            throw new BusinessException(ErrorCode.BUSINESS_ERROR, "Token 已过期，请重新登录");
        }

        // 2. 解析 Token 获取用户 ID
        Long userId = jwtUtil.getUserIdFromToken(token);
        User user = selectById(userId);
        if (user == null || user.getStatus() == 1) {
            throw new BusinessException(ErrorCode.BUSINESS_ERROR, "用户不存在或已删除");
        }

        // 3. 构建响应（排除密码等敏感字段）
        UserInfoResponse response = new UserInfoResponse();
        BeanUtils.copyProperties(user, response);
        response.setPassWord(null); // 屏蔽密码
        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUser(UserUpdateDTO updateDTO, Long operatorId) {
        // 1. 查询待修改用户
        User user = selectById(updateDTO.getId());
        if (user == null || user.getStatus() == 1) {
            throw new BusinessException(ErrorCode.BUSINESS_ERROR, "用户不存在或已删除");
        }

        // 2. 权限校验：仅本人或管理员可修改
        if (!user.getId().equals(operatorId)) {
            User operator = selectById(operatorId);
            if (operator == null || operator.getIdentity() != 2) { // 2-管理员
                throw new BusinessException(ErrorCode.PERMISSION_DENIED, "无权限修改他人信息");
            }
        }

        // 3. 构建更新实体（仅允许修改非敏感字段）
        BeanUtils.copyProperties(updateDTO, user, "id", "userName", "identity"); // 禁止修改 ID、用户名、身份
        if (updateDTO.getPassWord() != null) {
            // 密码修改：重新加密
            user.setPassWord(Md5Util.md5Encrypt(updateDTO.getPassWord()));
        }
        user.setUpdateByID(operatorId);
        user.setUpdateDateTime(new Date());

        return update(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteUser(Long deletedUserId, Long operatorId, Integer operatorIdentity, Integer operatorClassId) {
        // 1. 查询待删除用户
        User deletedUser = selectById(deletedUserId);
        if (deletedUser == null || deletedUser.getStatus() == 1) {
            throw new BusinessException(ErrorCode.BUSINESS_ERROR, "用户不存在或已删除");
        }

        // 2. 权限校验：学生无删除权限，老师仅删本班级用户，管理员无限制
        if (operatorIdentity == 0) { // 0-学生
            throw new BusinessException(ErrorCode.PERMISSION_DENIED, "学生无删除用户权限");
        } else if (operatorIdentity == 1) { // 1-老师
            if (!operatorClassId.equals(deletedUser.getClassID())) {
                throw new BusinessException(ErrorCode.PERMISSION_DENIED, "老师仅可删除本班级用户");
            }
        }
        // 管理员（identity=2）：无额外校验

        // 3. 软删除（修改 status 为 1）
        User user = new User();
        user.setId(deletedUserId);
        user.setStatus(1);
        user.setUpdateByID(operatorId);
        user.setUpdateDateTime(new Date());

        return update(user);
    }
}